//
//  CZHomeViewController.swift
//  GZWeibo009
//
//  Created by gzxzmac on 16/3/19.
//  Copyright © 2016年 gzxzmac. All rights reserved.
//

import UIKit

import SVPullToRefresh

class CZHomeViewController: CZBaseTableViewController {

    // MARK: - 属性
    private let ReuseIdentifier = "ReuseIdentifier"
    
    /// 微博数据
    var statuses: [CZStatus]? {
        didSet {
            self.tableView.reloadData()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // 登陆以后才做后面的操作
        if !CZUserAccountViewModel.sharedInstance.userLogin {
            return
        }
        
        // 设置导航栏
        setupNavigationBar()
        setupTitleButton()
        prepareTableView()
        
        // 显示FPS
        UIApplication.sharedApplication().keyWindow!.showInCenter()
    }
    
    private func prepareTableView() {
        // 注册cell
        tableView.registerClass(CZStatusCell.self, forCellReuseIdentifier: ReuseIdentifier)
        
        // cell的高度根据cell里面的子控件来自动布局来确定高度
        // 0.添加预估行高
        // 1.rowHeight = UITableViewAutomaticDimension
        // cell里面的约束要确定好.contentView的高度约束要根据子控件来,最终cell的高度会根据ContentView的高度来
//        tableView.estimatedRowHeight = 300
        tableView.rowHeight = UITableViewAutomaticDimension
        
        // 取消cell之间的分割线
        tableView.separatorStyle = UITableViewCellSeparatorStyle.None

        // 封装完成的下拉刷新控件
        tableView.addPullDownRefreshHandler({ [weak self] () -> () in
            self?.loadNewStatus()
        })
        
        tableView.startRefreshing()
        
        // 上拉加载更多
//        tableView.addInfiniteScrollingWithActionHandler { [weak self] () -> Void in
//            self?.loadMoreStatus()
//        }
    }
    
    /*
        1.一进入程序下拉刷新和上拉加载同时获取数据:不能既在下拉刷新又在上拉加载更多.因为AFN.GET是异步的,谁先回来不确定
            当第一次获取最新数据完成后再添加上拉加载更多功能
        2.用户网络不好,先下拉刷新,有上拉加载更多,同时存在2个请求,只能同时存在以个网络请求
    */
    
    /// 加载最新的微博数据
    private func loadNewStatus() {
        
        // 获取id最大的微博, 当没有微博数据,传入0加载最新20条微博数据
        let since_id = self.statuses?.first?.id ?? 0
        
//        weak var weakSelf = self <==> [weak self]
        
        // 使用VM加载数据
        // [weak self]: 闭包里面用得到的self都是weak的
        CZStatusListViewModel.sharedInstance.loadStatus(since_id, max_id: 0) { [weak self] (statuses, error) -> () in
            self?.tableView.endRefreshing()
            
            if error != nil {
                CZPrint(msg: "下拉刷新微博数据出错了: \(error)")
                return
            }
            
            let count = statuses?.count ?? 0
            
            if since_id > 0 {
                self?.showTipLabel(count)
            }
            
            if count == 0 {
                CZPrint(msg: "没有加载到微博")
                return
            }
            
            // 下拉刷新
            if since_id > 0 {
                print("下拉刷新count: \(count)")
                // 下拉刷新,需要将新获取到的数据添加到现有数据的前面,并且重新赋值
                self?.statuses = statuses! + self!.statuses!
                
            } else { // since_id = 0
                CZPrint(msg: "第一次加载最新微博count: \(count)")
                // 加载最新20条数据
                self?.statuses = statuses
                
                // 当第一次获取最新数据完成后再添加上拉加载更多功能
                self?.tableView.addInfiniteScrollingWithActionHandler { () -> Void in
                    self?.loadMoreStatus()
                }
            }
            CZPrint(msg: "最终微博数据条数: \(self?.statuses?.count)")
        }
    }
    
    /// 加载更多微博数据,上拉加载数据
    private func loadMoreStatus() {
        let max_id = self.statuses?.last?.id ?? 0
        
        CZStatusListViewModel.sharedInstance.loadStatus(0, max_id: max_id) { (statuses, error) -> () in
            // 结束上拉加载更多数据
            self.tableView.infiniteScrollingView.stopAnimating()
            
            if error != nil {
                CZPrint(msg: "上拉加载微博数据出错了: \(error)")
                return
            }
            
            let count = statuses?.count ?? 0
            
            if count == 0 {
                CZPrint(msg: "没有加载到微博")
                return
            }
            
            // 上拉加载更多数据,将新的数据拼接到现有数据的后面
            self.statuses = self.statuses! + statuses!
            CZPrint(msg: "上拉加载更多数据: \(statuses?.count)")
            CZPrint(msg: "最终微博数据条数: \(self.statuses?.count)")
        }
    }
    
    /**
     显示下拉刷新的条数
     
     - parameter count: 下拉刷新的条数
     */
    private func showTipLabel(count: Int) {
        tipLabel.text = count == 0 ? "没有新的微博数据" : "更新了\(count)条微博数据"
        
        // 动画叠加导致label还会往下走,UIView动画的底层也是核心动画
        let animationKeys = tipLabel.layer.animationKeys()
        if animationKeys != nil {
            CZPrint(msg: "有动画在运行,移除: \(animationKeys)")
            // 移除之前的动画
            tipLabel.layer.removeAllAnimations()
        }
        
        // 动画
        UIView.animateWithDuration(CZDefaultDuration * 4, animations: { () -> Void in
            self.tipLabel.frame.origin.y = 44
            }) { (_) -> Void in
                UIView.animateWithDuration(CZDefaultDuration * 4, delay: CZDefaultDuration * 2, options: UIViewAnimationOptions(rawValue: 0), animations: { () -> Void in
                    self.tipLabel.frame.origin.y = -64
                    }, completion: nil)
        }
    }
    
    /// 设置导航栏title
    private func setupTitleButton() {
        let name = CZUserAccountViewModel.sharedInstance.userAccount?.screen_name
        let titleButton = CZHomeTitleButton(title: name, imageName: "navigationbar_arrow_down")
        titleButton.addTarget(self, action: "didClickTitleButton:", forControlEvents: UIControlEvents.TouchUpInside)
        navigationItem.titleView = titleButton
    }

    /**
     设置导航栏左右
     */
    private func setupNavigationBar() {
        navigationItem.leftBarButtonItem = UIBarButtonItem(imageName: "navigationbar_friendsearch", target: self, action: "didClickLeftItem")
        navigationItem.rightBarButtonItem = UIBarButtonItem(imageName: "navigationbar_pop", target: self, action: "didClickRightItem")
    }
    
    // MARK: - 按钮点击事件
    @objc private func didClickTitleButton(button: CZHomeTitleButton) {
        // 当点击按钮的时候selected取反
        button.selected = !button.selected
        
        UIView.animateWithDuration(CZDefaultDuration) { () -> Void in
            button.imageView?.transform = button.selected ? CGAffineTransformMakeRotation(CGFloat(M_PI - 0.001)) : CGAffineTransformIdentity
        }
        
        if button.selected {
            // iOS8 以后 popoverPresentationController
            let popoverVC = CZPopoverViewController()
            
            // 只能用在iPad上面
//            UIPopoverController
            // UIAlertViewController: UIAlertView + UIActionSheet
            
            // 设置modal的显示样式
            popoverVC.modalPresentationStyle = .Popover
            
            // 设置popoverPresentationController的代理,实现代理的方法,来让popover不要适配iPhone
            popoverVC.popoverPresentationController?.delegate = self
            
            // popover的箭头指向titeView,默认指向左上角
            popoverVC.popoverPresentationController?.sourceView = navigationItem.titleView
            // 设置sourceView.bounds给sourceRect
            popoverVC.popoverPresentationController?.sourceRect = navigationItem.titleView!.bounds
            // 设置popover显示的大小
            popoverVC.preferredContentSize = CGSize(width: 200, height: 44 * popoverVC.titles.count)
            
            // 弹出
            presentViewController(popoverVC, animated: true, completion: nil)
        }
    }
    
    func didClickLeftItem() {
        CZPrint(msg: "didClickLeftItem")
    }
    
    func didClickRightItem() {
        CZPrint(msg: "didClickRightItem")
    }
    
    // MARK: - 懒加载
    /// 下拉刷新提示label
    private lazy var tipLabel: UILabel = {
        let tipLabel = UILabel()
        
        tipLabel.backgroundColor = UIColor.orangeColor()
        tipLabel.textColor = UIColor.whiteColor()
        tipLabel.font = UIFont.systemFontOfSize(16)
        tipLabel.textAlignment = NSTextAlignment.Center
        
        tipLabel.frame = CGRect(x: 0, y: -64, width: UIScreen.width, height: 44)
        
        // 往导航栏上面添加
        self.navigationController?.navigationBar.insertSubview(tipLabel, atIndex: 0)
        
        return tipLabel
    }()
}

// MARK: - 扩展 CZHomeViewController ,将 tableView相关的方法都写在这个扩展里面
extension CZHomeViewController {
    /*
        tableView的优化:
            1.cell复用
            2.图片加载(耗时操作)使用子线程(SDWebImage)
            3.IO操作(耗时操作),读取文件和写入文件,最好是在cell显示之前将文件的内容读取出来,保存在内存中
            4.缓存tableViewCell的行高,如果根据cell的约束确定行高,每当显示之前都需要计算
            5.不要使用预估行高,预估行高会使tableView的cell在显示之前才去计算
            6.dequeueReusableCellWithIdentifier:forIndexPath: 会再次调用 tableView:heightForRowAtIndexPath,所以尽量少用
            7.cell里面的控件使用懒加载.用不到的隐藏掉,不要在cellForRowAtIndexPath里面创建和删除子控件
            8.在tableView:cellForRowAtIndexPath:里面尽量少的计算
            9.使用图层圆角,阴影,会影响性能
            10.view或图层尽量使用不透明的
            11.图片的拉伸和压缩等都会影响性能
            12.cell在滚动的时候不要去做动画
            13.cell里面的view的层次不要太多
            14.AsyncDisplayKit -> UIKit Node (学习费劲)
    */
    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        // 将行高缓存到模型中,cell的内容是根据模型来的
        // 1.去模型中看看有没有缓存的行高
        let status = self.statuses![indexPath.row]
        if status.rowHeight != nil {
            // 模型中保存了行高
//            CZPrint(msg: "模型中保存了行高: \(indexPath), \(status.rowHeight!)")
            return status.rowHeight!
        }
        
//        CZPrint(msg: "没有缓存过行高")
        // 没有缓存过行高
        // 计算行高,autoLayout自动约束后可以拿到这个行高
        // 将模型赋值给cell
//        let cell = tableView.dequeueReusableCellWithIdentifier(ReuseIdentifier, forIndexPath: indexPath)
        let cell = tableView.dequeueReusableCellWithIdentifier(ReuseIdentifier) as! CZStatusCell
        
        // 将status赋值给cell,cell会根据status里面的内容和autoLayout,会重新计算布局,cell没有拿去显示,只是用来填充内容计算行高
        cell.status = status
        
        // 根据autolayout和cell控件的内容.获取cell的高度
        let rowHeight = cell.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize).height
        
        // 将计算好的行高保存到模型里面
        status.rowHeight = rowHeight
        
        return rowHeight
    }
    // 千万不要写到这个方法,返回多少组
//    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
//    }
    
    // 返回多少个cell
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // statuses?: statuses = nil 的时候就往后面走
        // ??: 表示 ?? 前面的可选如果没有值 就使用 ?? 后面的,
        return statuses?.count ?? 0
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(ReuseIdentifier) as! CZStatusCell

        cell.status = statuses?[indexPath.row]
        
        return cell
    }
    
    // 取消cell的选中
    override func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // cell不要高亮
        return false
    }
//    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//        tableView.deselectRowAtIndexPath(indexPath, animated: false)
//    }
    
    override func scrollViewDidScroll(scrollView: UIScrollView) {
//        CZPrint(msg: "scrollViewDidScroll")
        // 不要在这里来设置刷新控件.不然刷新控件太依赖控制器,刷新控件复用比较麻烦
    }
}

// MARK: - 扩展 CZHomeViewController 实现 UIPopoverPresentationControllerDelegate协议
extension CZHomeViewController: UIPopoverPresentationControllerDelegate {
    // 不让popover适配iPhone,默认适配.全屏的,不适配就是popover的效果
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        return UIModalPresentationStyle.None
    }
    
    // 系统会询问我们是否需要关闭popover
    func popoverPresentationControllerShouldDismissPopover(popoverPresentationController: UIPopoverPresentationController) -> Bool {
        // 让箭头转下来
        let titleButton = navigationItem.titleView as! CZHomeTitleButton
        didClickTitleButton(titleButton)
        
        return true
    }
}